package dk.aau.walkietalkie.network;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.annotation.SuppressLint;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
import dk.aau.walkietalkie.database.Identification;
import dk.aau.walkietalkieui.IMessageNotifier;
import dk.aau.walkietalkieui.WalkieTalkieApplication;
import dk.aau.walkietalkieui.message.MyMessage;
import dk.aau.walkietalkieui.message.MyMessage.MessageType;

public class TCPServerFileTransfer implements Runnable {

	private static final String IDENTIFICATION_SENDER = "IdentificationSender: ";
	public static final int RECEIVER_PORT = 8572;
	private static final String TAG = "TCPServerFileTransfer";
	private static final int LIMIT = 10000000;

	public static final String FILE_FOLDER_BASE_IMAGE = Environment
			.getExternalStorageDirectory().getAbsolutePath()
			+ "/walkie_talkie_aau/image/";

	public static final String FILE_NAME_BASE_IMAGE = "img_";

	public static final String FILE_FOLDER_BASE_AUDIO = Environment
			.getExternalStorageDirectory().getAbsolutePath()
			+ "/walkie_talkie_aau/audio/";

	public static final String FILE_NAME_BASE_AUDIO = "rec_";

	private boolean isRunning = false;
	private ServerSocket socketR;
	private BufferedReader entry;
	private DataOutputStream output;
	private String msgReceive_aux = null;
	private String msgReceive = " ";
	private IMessageNotifier mMsgNotifier;
	private String mDataPath;

	public TCPServerFileTransfer() {
		mMsgNotifier = null;
	}

	public void stopFileTransferServer() {
		isRunning = false;
	}

	public void setMessageNotifier(IMessageNotifier msgNotifier) {
		mMsgNotifier = msgNotifier;
	}

	@Override
	public void run() {

		// wait for the chat/contact list fragment to be created
		while (mMsgNotifier == null)
			;

		try {
			Socket socketReader = null;

			socketR = new ServerSocket(RECEIVER_PORT);
			isRunning = true;

			while (isRunning) {
				socketReader = socketR.accept();
				// buffer = new char[1024];
				entry = new BufferedReader(new InputStreamReader(
						socketReader.getInputStream()));

				// BufferedReader r = new BufferedReader(new
				// InputStreamReader(inputStream));
				StringBuilder total = new StringBuilder();
				String line;
				while ((line = entry.readLine()) != null) {
					total.append(line);
				}
				msgReceive = total.toString();
				// IOUtils.copy(inputStream,writer,encoding);
				// String theString = writer.toString();
				// msgReceive_aux = entry.readLine();

				// result = entry.read(buffer, 0, LIMIT);
				// while (result != -1) {
				// msgReceive = msgReceive + buffer.toString() ;
				// result = entry.read(buffer, msgReceive.length(), LIMIT);
				// }
				// entry.close();
				// msgReceive_aux = null;

				receivedMessageType(msgReceive);

				msgReceive = " ";

				socketReader.close();
			}

		} catch (Exception e) {
			// isConnected = false;
			e.printStackTrace();
			Log.e(TAG, "Error while receiving data: " + e.getMessage());
		}
	}

	private Object receivedMessageType(String msgReceive) {

		String IpSender;
		String NameSender;
		String IpReceiver;
		String NameReceiver;
		MessageType Type;
		String Data;

		Object screen = null;

		if (msgReceive != null) {
			// handle Ipsender
			IpSender = msgReceive.substring(
					msgReceive.indexOf(IDENTIFICATION_SENDER)
							+ IDENTIFICATION_SENDER.length(),
					msgReceive.indexOf("/#/"));

			// handle Namesender
			NameSender = msgReceive.substring(msgReceive.indexOf("/#/") + 3,
					msgReceive.indexOf("||"));

			Log.d("SENDER", " " + IpSender + " -> " + NameSender);

			// handle IpReceiver
			IpReceiver = msgReceive.substring(
					msgReceive.indexOf("IdentificationDestiny: ") + 23,
					msgReceive.indexOf("//#//"));

			// handle NameReceiver
			NameReceiver = msgReceive.substring(
					msgReceive.indexOf("//#//") + 5, msgReceive.indexOf("|||"));

			Log.d("RECEIVER", " " + IpReceiver + " -> " + NameReceiver);

			// handle type
			String strType = msgReceive.substring(
					msgReceive.indexOf("Type: ") + 6,
					msgReceive.indexOf("||||"));
			if (strType.equals("TYPE_RECORD")) {
				Type = MyMessage.MessageType.TYPE_RECORD;
			} else if (strType.equals("TYPE_PICTURE")) {
				Type = MyMessage.MessageType.TYPE_PICTURE;
			} else {
				Type = MyMessage.MessageType.TYPE_TEXT;
			}

			Log.d(TAG, " " + Type);

			// handle data
			Data = msgReceive.substring(msgReceive.indexOf("Data: ") + 6,
					msgReceive.indexOf(" END###!!!"));

			Log.v(TAG, "data-> " + Data + " ");

			// new message was received -> display it
			screen = convertToType(Data, Type);

			if (screen == null) {
				Log.e(TAG, "Msg not received !!!!");
				return null;
			}
			if (screen.getClass().equals(String.class)) {
				Log.e(TAG, "String msg received !!!!");
				// final String senderName = NameSender;
				// final String fileName = screen.toString();
				//
				// Handler mainHandler = new Handler(WalkieTalkieApplication
				// .getContext().getMainLooper());
				// Runnable myRunnable = new Runnable() {
				// @Override
				// public void run() {
				// Toast.makeText(
				// WalkieTalkieApplication.getContext(),
				// "Received Message from " + senderName + " in "
				// + fileName, Toast.LENGTH_LONG).show();
				// }
				// };
				// mainHandler.post(myRunnable);
				// return (String) screen;
				
				//Display the message in the chatMessageFragment
				mMsgNotifier.UpdateMessageView(new MyMessage(
						new Identification(IpSender, NameSender, 0), System
								.currentTimeMillis(), Type, new Identification(
								"me", "me", 0), screen.toString()));

			}
			if (screen.getClass().equals(FileOutputStream.class)) {
				mMsgNotifier.UpdateMessageView(new MyMessage(
						new Identification(IpSender, NameSender, 0), System
								.currentTimeMillis(), Type, new Identification(
								"me", "me", 0), mDataPath));

				// final String sendername = NameSender;
				// final String filepath = mDataPath;
				//
				// Handler mainHandler = new Handler(WalkieTalkieApplication
				// .getContext().getMainLooper());
				// Runnable myRunnable = new Runnable() {
				//
				// @Override
				// public void run() {
				//
				// Toast.makeText(
				// WalkieTalkieApplication.getContext(),
				// "Received file from " + sendername + " in "
				// + filepath, Toast.LENGTH_LONG).show();
				// }
				// };
				// mainHandler.post(myRunnable);

				Log.e(TAG, "String msg received !!!!");
				return screen.toString();
			}
		} else {
			Log.d(TAG, "Error Receiving data!!!");
			return null;

		}
		return null;
	}

	private String createUniqueFilename(final String nameBase) {
		boolean exists = true;
		int nameAddition = 0;
		Date now = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-DD_HH_mm_ss");
		String filePath = nameBase + formatter.format(now);

		while (exists) {
			exists = false;
			File f = new File(filePath + "_" + nameAddition);
			if (f.exists()) {
				nameAddition++;
				exists = true;
			} else {
				filePath = filePath + "_" + nameAddition;
			}
		}
		return filePath;
	}

	@SuppressLint("NewApi")
	public Object convertToType(String Data, MyMessage.MessageType Type) {
		byte[] image_byte = null;
		byte[] audio_byte = null;

		if (Type == MyMessage.MessageType.TYPE_RECORD) {
			audio_byte = Base64.decode(Data, Base64.DEFAULT);
			try {
				File audioDir = new File(FILE_FOLDER_BASE_AUDIO);
				audioDir.mkdirs();

				mDataPath = createUniqueFilename(FILE_FOLDER_BASE_AUDIO
						+ FILE_NAME_BASE_AUDIO)
						+ ".3gp";
				FileOutputStream audioOutFile = new FileOutputStream(mDataPath);
				audioOutFile.write(audio_byte);

				audioOutFile.close();
				Log.e(TAG, "New audio msg received !!!!");

				return audioOutFile;
			} catch (Exception e) {
				Log.d(TAG, "New audio msg not received !!!!");
			}

			return null;
		}

		if (Type == MyMessage.MessageType.TYPE_PICTURE) {
			image_byte = Base64.decode(Data, Base64.DEFAULT);
			try {
				File imgDir = new File(FILE_FOLDER_BASE_IMAGE);
				imgDir.mkdirs();

				mDataPath = createUniqueFilename(FILE_FOLDER_BASE_IMAGE
						+ FILE_NAME_BASE_IMAGE)
						+ ".jpg";
				FileOutputStream imageOutFile = new FileOutputStream(mDataPath);

				imageOutFile.write(image_byte);

				imageOutFile.close();
				Log.e(TAG, "New image msg received !!!!");

				return imageOutFile;

			} catch (Exception e) {
			}
			// image_byte = Base64.decode(Data, Base64.DEFAULT);
			// Bitmap decodedByte =
			// BitmapFactory.decodeByteArray(image_byte, 0,
			// image_byte.length);
			// String path =
			// Environment.getExternalStorageDirectory().toString();
			// OutputStream fOut = null;
			// File file = new File(path,"ReceivedPicture"+".jpg");
			// fOut = new FileOutputStream(file);
			// MediaStore.Images.Media.insertImage(getContentResolver(),
			// file.getAbsolutePath(), file.getName(), file.getName());

			Log.d(TAG, "New image msg not received !!!!");
			return null;

		}

		if (Type == MyMessage.MessageType.TYPE_TEXT) {
			Log.e(TAG, "New text msg received !!!!");
			return Data;
		}
		return null;
	}

}
